home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 228_01 / parser.c < prev    next >
Text File  |  1987-07-29  |  18KB  |  587 lines

  1. /*
  2. HEADER:         CUGXXX;
  3. TITLE:          Generalized, finite-state parser;
  4. DATE:           3-20-86;
  5. DESCRIPTION:    Powerful parser allowing extraction of single tokens from
  6.                 character strings.  User can specify delimiters/escape
  7.                 character.
  8. KEYWORDS:       Generalized finite-state parser, Parser;
  9. FILENAME:       PARSER.C;
  10. WARNINGS:       None;
  11. AUTHORS:        Lloyd Zusman;
  12. COMPILER:       DeSmet C;
  13. REFERENCES:     US-DISK 1308;
  14. ENDREF
  15. */
  16. #ifdef IGNORE_THIS
  17.  
  18. /*
  19.  
  20. NOTE:    lower down in this program description section, i have examples
  21.     of C code with embedded comments.  this "#ifdef" is here because
  22.     without it, the C compiler treats the end-of-comment delimiters
  23.     (asterisk-slash) as significant, and my examples start generating
  24.     code and errors.  the "#ifdef" causes this whole section to be
  25.     ignored, including the end-of-comment delimiters.
  26.  
  27.  
  28.     PARSER.C    Lloyd Zusman, Master Byte Software, Trump User Group
  29.             (408) 395-5693 (voice only)
  30.  
  31.     This program is a generalized, finite state token parser.  It's
  32.     it is the most powerful parser I've seen on any BBS (if I do say
  33.     so myself).  It allows you extract tokens one at a time from a
  34.     string of characters.  The characters used for white space, for
  35.     break characters, and for quotes can be specified.  Also,
  36.     characters in the string can be preceded by a specifiable escape
  37.     character which removes any special meaning the character may have.
  38.  
  39.     There are a lot of formal parameters in this subroutine call, but
  40.     once you get familiar with them, this routine is fairly easy to use.
  41.     "#define" macros can be used to generate simpler looking calls for
  42.     commonly used applications of this routine.
  43.  
  44.     First, some terminology:
  45.  
  46.     token            used here, a single unit of information in
  47.                 the form of a group of characters.
  48.  
  49.     white space        space that gets ignored (except within quotes
  50.                 or when escaped), like blanks and tabs.  in
  51.                 addition, white space terminates a non-quoted
  52.                 token.
  53.  
  54.     break character     a character that separates non-quoted tokens.
  55.                 commas are a common break character.  the
  56.                 usage of break characters to signal the end
  57.                 of a token is the same as that of white space,
  58.                 except multiple break characters with nothing
  59.                 or only white space between generate a null
  60.                 token for each two break characters together.
  61.  
  62.                 for example, if blank is set to be the white
  63.                 space and comma is set to be the break
  64.                 character, the line ...
  65.  
  66.                 A, B, C ,  , DEF
  67.  
  68.                 ... consists of 5 tokens:
  69.  
  70.                 1)    "A"
  71.                 2)    "B"
  72.                 3)    "C"
  73.                 4)    ""      (the null string)
  74.                 5)    "DEF"
  75.  
  76.     quote character     a character that, when surrounding a group
  77.                 of other characters, causes the group of
  78.                 characters to be treated as a single token,
  79.                 no matter how many white spaces or break
  80.                 characters exist in the group.    also, a
  81.                 token always terminates after the closing
  82.                 quote.    for example, if ' is the quote
  83.                 character, blank is white space, and comma
  84.                 is the break character, the following
  85.                 string ...
  86.  
  87.                 A, ' B, CD'EF GHI
  88.  
  89.                 ... consists of 4 tokens:
  90.  
  91.                 1)    "A"
  92.                 2)    " B, CD" (note the blanks & comma)
  93.                 3)    "EF"
  94.                 4)    "GHI"
  95.  
  96.                 the quote characters themselves do
  97.                 not appear in the resultant tokens.  the
  98.                 double quotes are delimiters i use here for
  99.                 documentation purposes only.
  100.  
  101.     escape character    a character which itself is ignored but
  102.                 which causes the next character to be
  103.                 used as is.  ^ and \ are often used as
  104.                 escape characters.  an escape in the last
  105.                 position of the string gets treated as a
  106.                 "normal" (i.e., non-quote, non-white,
  107.                 non-break, and non-escape) character.
  108.                 for example, assume white space, break
  109.                 character, and quote are the same as in the
  110.                 above examples, and further, assume that
  111.                 ^ is the escape character.  then, in the
  112.                 string ...
  113.  
  114.                 ABC, ' DEF ^' GH' I ^ J K^ L ^
  115.  
  116.                 ... there are 7 tokens:
  117.  
  118.                 1)    "ABC"
  119.                 2)    " DEF ' GH"
  120.                 3)    "I"
  121.                 4)    " "     (a lone blank)
  122.                 5)    "J"
  123.                 6)    "K L"
  124.                 7)    "^"     (passed as is at end of line)
  125.  
  126.  
  127.     OK, now that you have this background, here's how to call "parser":
  128.  
  129.     result=parser(flag,token,maxtok,string,white,break,quote,escape,
  130.               brkused,next,quoted)
  131.  
  132.     result:     0 if we haven't reached EOS (end of string), and
  133.             1 if we have (this is an "int").
  134.  
  135.     flag:        right now, only the low order 3 bits are used.
  136.             1 => convert non-quoted tokens to upper case
  137.             2 => convert non-quoted tokens to lower case
  138.             0 => do not convert non-quoted tokens
  139.             (this is a "char").
  140.  
  141.     token:        a character string containing the returned next token
  142.             (this is a "char[]").
  143.  
  144.     maxtok:     the maximum size of "token".  characters beyond
  145.             "maxtok" are truncated (this is an "int").
  146.  
  147.     string:     the string to be parsed (this is a "char[]").
  148.  
  149.     white:        a string of the valid white spaces.  example:
  150.  
  151.             char whitesp[]={" \t"};
  152.  
  153.             blank and tab will be valid white space (this is
  154.             a "char[]").
  155.  
  156.     break:        a string of the valid break characters.  example:
  157.  
  158.             char breakch[]={";,"};
  159.  
  160.             semicolon and comma will be valid break characters
  161.             (this is a "char[]").
  162.  
  163.             IMPORTANT:  do not use the name "break" as a C
  164.             variable, as this is a reserved word in C.
  165.  
  166.     quote:        a string of the valid quote characters.  an example
  167.             would be
  168.  
  169.             char whitesp[]={"'\"");
  170.  
  171.             (this causes single and double quotes to be valid)
  172.             note that a token starting with one of these characters
  173.             needs the same quote character to terminate it.
  174.  
  175.             for example,
  176.  
  177.             "ABC '
  178.  
  179.             is unterminated, but
  180.  
  181.             "DEF" and 'GHI'
  182.  
  183.             are properly terminated.  note that different quote
  184.             characters can appear on the same line; only for
  185.             a given token do the quote characters have to be
  186.             the same (this is a "char[]").
  187.  
  188.     escape:     the escape character (NOT a string ... only one
  189.             allowed).  use zero if none is desired (this is
  190.             a "char").
  191.  
  192.     brkused:    the break character used to terminate the current
  193.             token.    if the token was quoted, this will be the
  194.             quote used.  if the token is the last one on the
  195.             line, this will be zero (this is a pointer to a
  196.             "char").
  197.  
  198.     next:        this variable points to the first character of the
  199.             next token.  it gets reset by "parser" as it steps
  200.             through the string.  set it to 0 upon initialization,
  201.             and leave it alone after that.    you can change it
  202.             if you want to jump around in the string or re-parse
  203.             from the beginning, but be careful (this is a
  204.             pointer to an "int").
  205.  
  206.     quoted:     set to 1 (true) if the token was quoted and 0 (false)
  207.             if not.  you may need this information (for example:
  208.             in C, a string with quotes around it is a character
  209.             string, while one without is an identifier).
  210.  
  211.             (this is a pointer to a "char").
  212.  
  213.     Example 1:
  214.  
  215.     char *whitesp[]={" \t");        /* blank and tab */
  216.     char *breakch[]={",\r");        /* comma and carriage return */
  217.     char *quotech[]={"'\""};        /* single and double quote */
  218.     char escape='^';                /* "uparrow" is escape */
  219.  
  220.     main()
  221.     {
  222.       char *fgets(),line[81],brkused,quoted,token[81];
  223.       int i,next;
  224.  
  225.       while(fgets(line,80,stdin)!=NULL)    /* get line */
  226.       {
  227.  
  228.         printf("Line: %s",line);            /* already has <CR> */
  229.         i=0;
  230.  
  231.         next=0;                /* make sure you do this */
  232.  
  233.         while(parser(2,token,80,line,whitesp,breakch,quotech,escape,
  234.              &brkused,&next,"ed)==0)
  235.         {
  236.           printf(" Token %d = (%s)\n",++i,token);
  237.  
  238.           if(brkchar=='\r') /* <CR> is a break so it won't be included  */
  239.         break;        /* in the token.  treat as end-of-line here */
  240.         }
  241.       }
  242.     }
  243.  
  244.  
  245.  
  246.     In the above example, lines are read from stdin and broken up into
  247.     tokens.  All non-quoted tokens are converted to lower case.  Since
  248.     fgets() returns the final carriage return, we treat it as a break
  249.     character to keep it out of the returned token.  Also, since the only
  250.     way "parser" will return a non-zero error code is at end of line,
  251.     we test "brkchar" to see if we've gotten to the final carriage
  252.     return, and we explicitly break ou